package com.softserveinc.ita.kaiji.model.game;

import com.softserveinc.ita.kaiji.model.*;
import com.softserveinc.ita.kaiji.model.player.Player;

import java.util.*;

/**
 * @author Paziy Evgeniy
 * @version 2.3
 * @since 17.03.14
 */
class GameHistoryImpl implements GameHistory {

    private Integer id;

    private GameInfo gameInfo;
    private Player winner = null;
    private Map<Player, Map<Card.DuelResult, Integer>> statistic;
    private List<RoundResult> roundResults;
    private Game.State gameState;


    GameHistoryImpl(GameInfo gameInfo, List<RoundResult> roundResults, Game.State gameState) {
        this.gameInfo = gameInfo;
        this.roundResults = roundResults;
        this.gameState = gameState;

        calculateStatistic();
        determineWinner();
    }

    private void calculateStatistic() {
        statistic = new HashMap<>(gameInfo.getPlayers().size());

        for (Player p : gameInfo.getPlayers()) {
            Map<Card.DuelResult, Integer> statisticEntry = new HashMap<>(Card.DuelResult.values().length);

            for (Card.DuelResult dr : Card.DuelResult.values()) {
                int countForSuchResult = 0;

                for (RoundResult rs : roundResults) {
                    Card.DuelResult duelResult = rs.getDuelResult(p);
                    if (dr == duelResult) {
                        ++countForSuchResult;
                    }
                }

                statisticEntry.put(dr,countForSuchResult);
            }


            statisticEntry = Collections.unmodifiableMap(statisticEntry);
            statistic.put(p, statisticEntry);
        }

        statistic = Collections.unmodifiableMap(statistic);
    }

    //todo will be changed
    private void determineWinner() {

        Map<Integer, Player> wins = new HashMap<>();

        for (Player p : gameInfo.getPlayers()) {
            int winCount = statistic.get(p).get(Card.DuelResult.WIN);
            wins.put(winCount, p);
        }

        //second player override result of firs player - draw
        if (wins.size() == 1) {
            return;
        }

        //find max win rate
        Integer max = -1;
        for (Integer i : wins.keySet()) {
            if (max < i) {
                max = i;
            }
        }

        //winner have max wins
        winner = wins.get(max);
    }

    @Override
    public GameInfo getGameInfo() {
        return gameInfo;
    }

    @Override
    public List<RoundResult> getRoundResults() {
        return roundResults;
    }

    @Override
    public RoundResult getLastRoundResult() {
        if (roundResults.isEmpty()) {
            return null;
        } else {
            return roundResults.get(roundResults.size() - 1);
        }
    }

    @Override
    public Player getWinner() {
        return winner;
    }

    @Override
    public Map<Card.DuelResult, Integer> getStatisticFor(Player player) {
        return statistic.get(player);
    }

    @Override
    public Game.State getGameStatus() {
        return gameState;
    }

    @Override
    public void setId(Integer id) {
        this.id = id;
    }

    @Override
    public Integer getId() {
        return id;
    }
}

